package  
{
  
  import flash.display.Sprite;
  import flash.events.Event;
  import flash.events.MouseEvent;
  import flash.geom.Point;
  import flash.geom.Rectangle;
  import flash.ui.Keyboard;
  import mge.graph.AStar;
  import mge.graph.Graph;
  import mge.graph.Node;
  
	/**
   * ...
   * @author ivan
   */
  public class Selection extends Sprite
  {
    
    public function Selection(graphStage:GraphStage) 
    {
      this.graphStage = graphStage;
      
      items = new Vector.<Sprite>();
      mouseEnabled = false;
      addEventListener(Event.ENTER_FRAME, onEnterFrame);
      
      addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
    }
    
    private function onAddedToStage(e:Event):void
    {
      removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
      
      parent.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
      parent.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
      parent.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
    }
    
    private function onMouseDown(e:MouseEvent):void
    {
      if (!enabled) return;
      if (e.target != graphStage && (e.target as Sprite).parent != graphStage) return;
      mouseDown = true;
      mouseDownPoint = new Point(e.localX, e.localY);
      trace(mouseDownPoint);
      
      if (!e.shiftKey && !overSelection(e))
      {
        items.splice(0, items.length);
      }
      if (e.target as VisualNode || e.target as VisualEdge)
      {
        // Over draggable object
        var s:Sprite = e.target as Sprite;
        if (items.indexOf(s) == -1)
          items.push(e.target as Sprite);
        dragOrigin = new Point(s.x, s.y);
        mouseDownOverItem = true;
      }
      
      if (overSelection(e)) mouseDownOverItem = true;
    }
    
    private function overSelection(e:MouseEvent):Boolean
    {
      var s:Sprite = (e.target as Sprite);
      return items.indexOf(s) != -1;
    }
    
    private function onMouseUp(e:MouseEvent):void
    {
      if (!enabled) return;
      if (dragging)
      {
        graphStage.dragSelection();
      }
      
      if (selectingArea)
      {
        var rect:Rectangle = new Rectangle();
        for (var i:int = 0; i < graphStage.numChildren; i++)
        {
          var s:Sprite = graphStage.getChildAt(i) as Sprite;
          if ( s && areaSelected.containsPoint(new Point(s.x, s.y)) )
          {
            items.push(s);
          }
        }
      }
      
      x = y = 0;
      mouseDown = false;
      dragging = false;
      selectingArea = false;
      mouseDownOverItem = false;
    }
    
    private function onMouseMove(e:MouseEvent):void
    {
      if (!enabled) return;
      if (mouseDown)
      {
        if (mouseDownOverItem) dragging = true;
        else selectingArea = true;
      }
      
      if (dragging)
      {
        x = e.localX - dragOrigin.x;
        y = e.localY - dragOrigin.y;
      }
      
      if (selectingArea)
      {
        if (! (e.target as GraphStage))
          return;
          
        areaSelected = new Rectangle(mouseDownPoint.x, mouseDownPoint.y, e.localX - mouseDownPoint.x, e.localY - mouseDownPoint.y);
      }
    }
    
    private function onEnterFrame(e:Event):void
    {
      // TEMP TEST PATHFINDING SELECTING PATH
      /*
      if (!enabled)
      {
          var g:Graph = graphStage.graph;
          var astar:AStar = new AStar();
          astar.graph = g;
          var nodes:Vector.<Node> = astar.findPath(g.nodes[0], g.nodes[g.nodes.length-1]);
          items.splice(0, items.length);
          if (nodes)
          for (i = 0; i < graphStage.numChildren; i++)
          {
            ve = graphStage.getChildAt(i) as VisualEdge;
            if (ve)
            {
              if (nodes.indexOf(ve.edge.source) != -1 && nodes.indexOf(ve.edge.target) != -1)
                items.push(ve);
            }
          }
          
          graphics.clear();
          
          graphics.beginFill(0xFFFF00, 0.25);
          for (var i:int = 0; i < items.length; i++)
          {
            graphics.lineStyle(1, 0xFFFF00);
            var s:Sprite = items[i];
            if (s as VisualNode)
              graphics.drawRect(s.x - s.width / 2, s.y - s.height / 2, s.width, s.height);
            else if (s as VisualEdge)
            {
              graphics.lineStyle(3, 0xFFFF00);
              var ve:VisualEdge = s as VisualEdge;
              graphics.moveTo(ve.edge.source.x, ve.edge.source.y);
              graphics.lineTo(ve.edge.target.x, ve.edge.target.y);
            }
          }
          
          if (selectingArea)
          {
            graphics.drawRect(areaSelected.x, areaSelected.y, areaSelected.width, areaSelected.height);
          }
          
          graphics.endFill();
          return;
      }*/
      // TEMP TEST
      
      graphics.clear();
      if (!enabled) return;
      
      graphics.beginFill(0xFFFF00, 0.25);
      for (var i:int = 0; i < items.length; i++)
      {
        graphics.lineStyle(1, 0xFFFF00);
        var s:Sprite = items[i];
        if (s as VisualNode)
          graphics.drawRect(s.x - s.width / 2, s.y - s.height / 2, s.width, s.height);
        else if (s as VisualEdge)
        {
          graphics.lineStyle(3, 0xFFFF00);
          var ve:VisualEdge = s as VisualEdge;
          graphics.moveTo(ve.edge.source.x, ve.edge.source.y);
          graphics.lineTo(ve.edge.target.x, ve.edge.target.y);
        }
      }
      
      if (selectingArea)
      {
        graphics.drawRect(areaSelected.x, areaSelected.y, areaSelected.width, areaSelected.height);
      }
      
      graphics.endFill();
    }
    
    public var items:Vector.<Sprite>;
    public var enabled:Boolean;
    
    private var mouseDownPoint:Point;
    private var mouseDown:Boolean;
    private var mouseDownOverItem:Boolean;
    private var dragging:Boolean;
    private var selectingArea:Boolean;
    private var areaSelected:Rectangle;
    private var dragOrigin:Point;
    
    private var graphStage:GraphStage;
  }

}